//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include "tp_print.h"

#ifdef _x86
#include "x86/cpu.h"
#elif defined _sharp
#include "arm/sharp/cpu.h"
#elif defined _techfaith
#include "arm/techfaith/cpu.h"
#elif defined _gingko
#include "arm/gingko/cpu.h"
#elif defined _c28
#include "arm/c28/cpu.h"
#elif defined _neptune
#include "arm/neptune/cpu.h"
#endif

#define FREQUENCY 500/*000000*/

void TestKernelExit()
{
    Cli();
    timepeg_read_proc();
}

void zap_all_timepegs(void)
{
    struct timepeg_slot *slotp = g_timepeg_slots;

    for (; slotp; slotp = slotp->next) {
        int pred;
        /* Leave departure_tp alone */

        for (pred = 0; pred < TIMEPEG_NR_PREDS; pred++) {
            struct timepeg_arc *arc = &(slotp->preds[pred]);
            arc->timepeg = 0;
            arc->acc_tp.high = 0;
            arc->acc_tp.low = 0;
            arc->min_tp.high = (unsigned long)-1;
            arc->min_tp.low = (unsigned long)-1;
            arc->max_tp.high = 0;
            arc->max_tp.low = 0;
            arc->nr_times = 0;
        }
    }
    return;
}

void timepeg_read_proc()
{
    struct timepeg_slot *ntps;

    if (0 == g_timepeg_slots) {
        return;
    }

    kprintf("(g_timepeg_slots:%x)\r\n", g_timepeg_slots);
    for (int Delay = 0; Delay < 0xfffff; Delay++);
    kprintf("Thread Schedule Latency Testing\n");
    struct timepeg_slot * temp = g_timepeg_slots;
    while (temp) {
        // We search the nodes from the back to the front,
        // and one of the first
        // node's pointers named directed_pred is used to
        // specify it's previous
        // node's address, but it has been initialized to NULL.
        // So, break this recycle while that condition occurs.
        if (!temp->directed_pred) {
            break;
        }

        kprintf("------------PERFORMANCE_JUNNING_VALUE_START(%s)\n",
            temp->name);
        int j = 0;
        UInt32 * result = &(temp->value[j]);
        while (j < TST_TIMES) {
            kprintf("value[%4d] = %d\r\n", j, *result);
            result++;
            j++;
            for (int Delay = 0; Delay < 0xfffff; Delay++);
        }
        kprintf("------------PERFORMANCE_JUNNING_VALUE_END\n");

        temp = temp->next;
    }

    kprintf("******PERFORMANCE_BSP_RENCHI\n");
    for (ntps = g_timepeg_slots; ntps; ntps = ntps->next) {
        int j, n = 0;

        for (j = 0; j < TIMEPEG_NR_PREDS; j++) {
            struct timepeg_arc *ntpa;
            ntpa = &(ntps->preds[j]);
            if (ntpa->timepeg)
                n++;
            else
                break;
        }

        for (j = 0; j < TIMEPEG_NR_PREDS; j++) {
            struct timepeg_arc *ntpa;
            ntpa = &(ntps->preds[j]);
            if (ntpa->timepeg) {
                kprintf("%10s\n", ntpa->timepeg->name);
                kprintf("-->\n");
                if (ntpa->nr_times > 2) {
                    kprintf("%s,ClockCycle,%lu%lu,%lu%lu,%lu%lu,null\n",
                    ntps->name,
                    ntpa->acc_tp.high, (ntpa->acc_tp.low - ntpa->min_tp.low \
                        - ntpa->max_tp.low) / (ntpa->nr_times - 2),
                    ntpa->max_tp.high, ntpa->max_tp.low,
                    ntpa->min_tp.high, ntpa->min_tp.low);
                }
                else {
                    kprintf("%s,ClockCycle,%lu%lu,%lu%lu,%lu%lu,null\n",
                    ntps->name,
                    ntpa->max_tp.high, ntpa->max_tp.low,
                    ntpa->max_tp.high, ntpa->max_tp.low,
                    ntpa->min_tp.high, ntpa->min_tp.low);
                }
            }
            // if ntpa->timepeg==NULL, break this "for"
            else {
                break;
            }
        }
    }
    kprintf("******PERFORMANCE_BSP_RENCHI_END\n");

    kprintf("$OUT");

    zap_all_timepegs();

    return;
}
